package tracker.model.tests;

import junit.framework._
import junit.framework.Assert._
import java.util.Date
import bamboo.util.TimeSpan

class TimeTrackingSystemTestCase extends TestCase {
  
  val FILENAME = "time.db4o"
    
  var system: TimeTrackingSystem = null
  
  val project1 = new Project("db4o")
  val project2 = new Project("test")
  val task1 = new Task(project1, "transparent activation")
  val task2 = new Task(project2, "er")
  val task3 = new Task(project2, "ar")
  
  override def setUp() {
    new java.io.File(FILENAME).delete()
    system = new TimeTrackingSystem(FILENAME)
    
    system.addTask(task1)
    system.addTask(task2)
    system.addTask(task3)
  }
  
  override def tearDown() { 
    if (system != null) system.dispose() 
  }
  
  def testUpdateRefusesNewObjects() {
    expect(classOf[IllegalArgumentException]) {
      system.update(new Task(project1, "foo"))
    }
  }
  
  def testUpdate() {
    val a = new Activity(task1, new Date(), new Date())
    system.addActivity(a)
    a.notes = "foo"
    system.update(a)
  }
 
  def testProjectsSortedByName() = {      
    assertEquals(List(project1, project2), system.projects.toList)
  }
  
  def testTasksSortedByName() {
    assertEquals(List(task1), system.tasks.forProject(project1).toList)
    assertEquals(List(task3, task2), system.tasks.forProject(project2).toList)
  }
  
  def testActivities()  {
    val a1 = new Activity(task1, new Date(2007, 7, 20, 17, 50), new Date(2007, 7, 20, 18, 31))
    val a2 = new Activity(task2, new Date(2007, 7, 26), new Date(2007, 7, 27))
    assertEquals(TimeSpan.minutes(41), a1.elapsed)
    
    system.addActivity(a1)
    system.addActivity(a2)
    
    assertElements(system.activities, a1, a2)
    
    assertElements(system.activities.forProject(task1.project), a1)
    assertElements(system.activities.forProject(task2.project), a2)
    
    assertElements(system.activities.from(a1.started), a1, a2)
    assertElements(system.activities.from(a2.started), a2)
  }
  
  def assertElements[T](i: Iterable[T], expected: T*) {
    var remaining = i.toList
    expected.foreach { item =>
    	assertTrue(remaining.contains(item))
        remaining = remaining.remove(_ == item)
    }
    assertEquals(List(), remaining)
  }
  
  def expect[T](exception: Class[T])(block: => Unit): Unit = {
    var found: Throwable = null
    try {
      block
    } catch {
      case e => found = e
    }
    if ((found eq null) || !exception.isInstance(found)) {
      fail("Expecting " + exception)
    }
  }
}

